package com.party.admin.biz.activity;


import com.alibaba.fastjson.JSONObject;
import com.google.common.base.Strings;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.party.admin.biz.file.FileBizService;
import com.party.admin.biz.quartz.IScheduleJobService;
import com.party.admin.biz.quartz.impl.SchsduleService;
import com.party.admin.biz.system.MemberGroupBizService;
import com.party.admin.web.dto.AjaxResult;
import com.party.common.constant.Constant;
import com.party.common.redis.StringJedis;
import com.party.common.utils.BigDecimalUtils;
import com.party.common.utils.DateUtils;
import com.party.common.utils.StringUtils;
import com.party.core.exception.BusinessException;
import com.party.core.model.BaseModel;
import com.party.core.model.YesNoStatus;
import com.party.core.model.activity.Activity;
import com.party.core.model.crowdfund.Project;
import com.party.core.model.member.MemberGroup;
import com.party.core.model.notify.Event;
import com.party.core.model.notify.InstanceWay;
import com.party.core.model.notify.TargetTemplate;
import com.party.core.model.notify.TargetTemplateType;
import com.party.core.model.quartz.QuartzDataMap;
import com.party.core.service.activity.IActivityService;
import com.party.core.service.crowdfund.IProjectService;
import com.party.core.service.crowdfund.ITargetTemplateService;
import com.party.core.service.member.IMemberGroupService;
import com.party.core.service.member.IThirdMemberService;
import com.party.core.service.notify.IEventService;
import com.party.core.service.quartz.IQuartzDataMapService;
import com.party.notify.notifyPush.activity.ActivitySendFactory;
import com.party.notify.notifyPush.activity.INotifyActivitySendService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.text.ParseException;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Random;

/**
 * 活动业务接口
 * Created by wei.li
 *
 * @date 2017/3/22 0022
 * @time 17:44
 */
@Service
public class ActivityBizService {

    @Autowired
    private FileBizService fileBizService;

    @Autowired
    private IProjectService projectService;

    @Autowired
    private ITargetTemplateService targetTemplateService;

    @Autowired
    private IActivityService activityService;

    @Autowired
    private ActivitySendFactory activitySendFactory;

    @Autowired
    private IThirdMemberService thirdMemberService;

    @Autowired
    private IScheduleJobService scheduleJobService;

    @Autowired
    private IEventService eventService;

    @Autowired
    private IQuartzDataMapService quartzDataMapService;


    @Autowired
    private MemberGroupBizService memberGroupBizService;

    @Autowired
    private StringJedis stringJedis;

    @Autowired
    private IMemberGroupService memberGroupService;

    private static Logger logger = LoggerFactory.getLogger(ActivityBizService.class);

    /**
     * 拼接分销连接
     *
     * @param id 活动编号
     * @param memberId 创建者
     * @return 分销连接
     */
    public String getDistributionUrl(String id, String memberId){
        StringBuilder stringBuilder = new StringBuilder("hd/hd_distribution.html?");
        stringBuilder.append("id=").append(id)
                .append("&parentId=").append("0")
                .append("&distributorId=").append(memberId);
        return stringBuilder.toString();
    }

    /**
     * 众筹项目众筹了多少资金
     *
     * @param targetId 目标编号
     * @return 资金
     */
    public float actualAmountForTargetId(String targetId){
        List<Project> projectList = projectService.listForTargetId(targetId);
        float actualAmount = 0f;
        for (Project project : projectList){
            actualAmount = BigDecimalUtils.add(actualAmount, project.getActualAmount());
        }
        actualAmount = BigDecimalUtils.round(actualAmount, 2);
        return actualAmount;
    }

    /**
     * 获取目标模板
     *
     * @param targetId 模板编号
     * @param type 类型
     * @return 模板编号
     */
    public TargetTemplate getTemplate(String targetId, Integer type){
        type = null == type ? TargetTemplateType.ACT_STATUS_AUDITING.getCode() : type;
        TargetTemplate targetTemplate = targetTemplateService.findByTargetId(targetId, type);
        if (null == targetTemplate){
            targetTemplate = new TargetTemplate();
            targetTemplate.setType(type);
            targetTemplate.setTargetId(targetId);
        }
        return targetTemplate;
    }

    /**
     * 发送消息and保存模板
     *
     * @param targetTemplate 目标模板
     */
    public void sendAndSave(TargetTemplate targetTemplate){
        if (Strings.isNullOrEmpty(targetTemplate.getTemplate())){
            throw new BusinessException("模板内容不能为空");
        }
        Activity activity = activityService.get(targetTemplate.getTargetId());
        if (null == activity){
            throw new BusinessException("找不到众筹项目");
        }

        //保存
        targetTemplate.setId(null);
        targetTemplate.setInitiatorId(activity.getMember());
        Date now = new Date();
        targetTemplate.setCreateDate(now);
        targetTemplate.setUpdateDate(now);
        targetTemplate.setSendTime(now);
        targetTemplateService.insert(targetTemplate);
        this.activityRealSend(targetTemplate, activity.getMember());

    }

    public String save(TargetTemplate targetTemplate) {
        if (Strings.isNullOrEmpty(targetTemplate.getTemplate())){
            throw new BusinessException("模板内容不能为空");
        }
        Activity activity = activityService.get(targetTemplate.getTargetId());
        if (null == activity){
            throw new BusinessException("找不到众筹项目");
        }

        //保存
        targetTemplate.setInitiatorId(activity.getMember());
        return targetTemplateService.insert(targetTemplate);
    }

    /**
     * 发送消息and保存模板
     * @param id 目标模板id
     */
    public void send(String id) {
        TargetTemplate targetTemplate = targetTemplateService.get(id);
        if (Strings.isNullOrEmpty(targetTemplate.getTemplate())) {
            throw new BusinessException("模板内容不能为空");
        }
        Activity activity = activityService.get(targetTemplate.getTargetId());
        if (null == activity) {
            throw new BusinessException("找不到活动");
        }

        this.activityRealSend(targetTemplate, activity.getMember());
    }

    /**
     * 活动短信真实发送
     *
     * @param targetTemplate 模板
     * @param orgId          机构id
     */
    public void activityRealSend(TargetTemplate targetTemplate, String orgId) {
        TargetTemplateType targetTemplateType = TargetTemplateType.get(targetTemplate.getType());
        INotifyActivitySendService notifyActivitySendService = activitySendFactory.getSender(targetTemplateType);
        notifyActivitySendService.send(targetTemplate.getTargetId(), orgId,
                targetTemplate, InstanceWay.SYSTEM.getName());
    }

    /**
     * 初始化活动的二维码
     */
    public void uploadActivityQrCodeCI() {
        Activity activity = new Activity();
        activity.setDelFlag(BaseModel.DEL_FLAG_NORMAL);
        activity.setIsCrowdfunded(YesNoStatus.NO.getCode());
        List<Activity> activities = activityService.list(activity);
        for (Activity act : activities) {
            String publisher = act.getMember();
            if (StringUtils.isEmpty(publisher)) {
                continue;
            }
            String cloudFilePath = fileBizService.getUploadCIPath(publisher, "activity");

            /*** 详情二维码 ***/
            String fileName = "detail_" + act.getId();
            String localFilePath = publisher + "/activity/";
            String content = "hd/hd_detail.html?hdId=" + act.getId();
            fileBizService.uploadCloudOut(fileName, cloudFilePath, localFilePath, act.getId(), content, publisher);

            /*** 签到二维码 ***/
            String bmFileName = "sign_" + act.getId();
            String signPath = publisher + "/activity/memberAct/";
            String bmContent = "hd/hdbm_sign.html?hdId=" + act.getId();
            fileBizService.uploadCloudOut(bmFileName, cloudFilePath, signPath, act.getId(), bmContent, publisher);

            /*** 分销二维码 ***/
            String fxFileName = "fx_" + act.getId();
            String disPath = publisher + "/distribution/";
            String fxContent = getDistributionUrl(act.getId(), publisher);
            fileBizService.uploadCloudOut(fxFileName, cloudFilePath, disPath, act.getId(), fxContent, publisher);
        }
    }

    /**
     * 初始化众筹项目的二维码
     */
    public void uploadZcActivityQrCodeCI() {
        Activity activity = new Activity();
        activity.setDelFlag(BaseModel.DEL_FLAG_NORMAL);
        activity.setIsCrowdfunded(YesNoStatus.YES.getCode());
        List<Activity> activities = activityService.list(activity);
        for (Activity act : activities) {
            String publisher = act.getMember();
            if (StringUtils.isEmpty(publisher)) {
                continue;
            }

            /*** 详情二维码 ***/
            String filePath = fileBizService.getUploadCIPath(publisher, "zcActivity");

            /*** 众筹项目详情二维码 ***/
            String xqFileName = "detail_" + act.getId();
            String detailContent = "project/target_client_detail.html?id=" + act.getId();
            fileBizService.uploadCloudOut(xqFileName, filePath, detailContent, publisher, 0);

            /*** 众筹联合发起二维码 ***/
            String dyFileName = "dy_" + act.getId();
            String dyContent = "project/target_detail.html?id=" + act.getId();
            fileBizService.uploadCloudOut(dyFileName, filePath, dyContent, publisher, 0);
        }
    }

    /**
     * 生成信息
     *
     * @param activityId 项目id
     * @return 信息集合
     */
    public Map<String, Object> generateInfo(String activityId) {
        Map<String, Object> result = Maps.newHashMap();
        Integer account = (int) ((Math.random() * 9 + 1) * 100000);
        List<String> thirdList = thirdMemberService.allAccount();
        List<Integer> lists = Lists.newArrayList();
        generateAccount(thirdList, account, lists);
        result.put("account", lists.get(0));
        String password = getStringRandom(6);
        result.put("password", password.toLowerCase());
        String alias = "/activity/zcActivity/third/";
        String url = alias + "editCrowdActivity.do?id=" + activityId;
        result.put("url", url);
        result.put("alias", alias);
        return result;
    }

    public boolean generateAccount(List<String> thirdList, Integer account, List<Integer> lists) {
        lists.add(account);
        boolean flag = true;
        for (String str : thirdList) {
            if (account.toString().equals(str)) {
                flag = false;
                lists.remove(Integer.valueOf(str));
                break;
            } else {
                flag = true;
            }
        }

        if (flag == false) {
            account = (int) ((Math.random() * 9 + 1) * 100000);
            flag = generateAccount(thirdList, account, lists);
        }
        return flag;
    }

    /**
     * 生成随机数字和字母
     *
     * @param length 长度
     * @return 随机数字符串
     */
    public String getStringRandom(int length) {
        String val = "";
        Random random = new Random();

        //参数length，表示生成几位随机数
        for (int i = 0; i < length; i++) {
            String charOrNum = random.nextInt(2) % 2 == 0 ? "char" : "num";
            //输出字母还是数字
            if ("char".equalsIgnoreCase(charOrNum)) {
                //输出是大写字母还是小写字母
                int temp = random.nextInt(2) % 2 == 0 ? 65 : 97;
                val += (char) (random.nextInt(26) + temp);
            } else if ("num".equalsIgnoreCase(charOrNum)) {
                val += String.valueOf(random.nextInt(10));
            }
        }
        return val;
    }

    /**
     * 消息推送-定时
     * @param targetTemplate
     * @param dateTime: 格式为yyyy-MM-dd HH:mm:ss
     * @param type: 1: 众筹项目 2: 众筹事件
     * @return
     */
    @Transactional
    public AjaxResult sendQuartz(TargetTemplate targetTemplate, String dateTime, String behavior, Integer type) {
        AjaxResult ajaxResult = new AjaxResult();
        Date date = null;
        if (StringUtils.isEmpty(dateTime)) {
            return AjaxResult.error("dateTime不能为空");
        }
        if (dateTime.indexOf(":") == dateTime.lastIndexOf(":")) {
            dateTime = dateTime + ":00";
        }
        try {
            date = DateUtils.parse(dateTime, "yyyy-MM-dd HH:mm:ss");
        } catch (ParseException e) {
            logger.error("定时推送短信失败, 时间参数有误 dateTime = {}", dateTime, e);
            ajaxResult.setDescription("定时推送短信失败, 时间参数有误 dateTime = " + dateTime);
            ajaxResult.setSuccess(false);
            return ajaxResult;
        }

        // 定时的时间小于当前时间, 则直接立即执行
        if (date.getTime() < System.currentTimeMillis()) {
            if ("add".equals(behavior)) {
                this.sendAndSave(targetTemplate);
            } else if ("modifyTime".equals(behavior)){
                return AjaxResult.error("时间参数有误, 该时间将永远不会执行 dateTime = " + dateTime);
            } else {
                this.send(targetTemplate.getId());
            }
            return AjaxResult.success();
        }

        targetTemplate.setSendTime(date);
        String tempId = null;
        boolean hasTemp;
        if ("add".equals(behavior)) {
            targetTemplate.setId(null);
            if (Constant.SEND_SHORT_MESSAGE_TYPE_ACTIVITY.equals(type)) {
                tempId = this.save(targetTemplate);
            }
            hasTemp = false;
        } else {
            // 如果是修改发送时间, 需要检测该短信是否已经发送了
            if ("modifyTime".equals(behavior)) {
                TargetTemplate dbTemp = targetTemplateService.get(targetTemplate.getId());
                Date sendTime = dbTemp.getSendTime();
                if (null != sendTime && sendTime.getTime() < System.currentTimeMillis()) {
                    return AjaxResult.error("该短信已经发送了, 请刷新页面");
                }
            }
            targetTemplateService.update(targetTemplate);
            tempId = targetTemplate.getId();
            hasTemp = true;
        }

        if (StringUtils.isEmpty(tempId)) {
            return AjaxResult.error("保存定时发送短信模板失败, template = " + targetTemplate);
        }

        String cron = DateUtils.formatDate(date, "s m HH d M ? yyyy");

        final String clazz = "quartzBizSendShortMessage";
        final String method = "send";

        List<Object> params = Lists.newArrayList();
        params.add(type);

        Event event;
        if (hasTemp) {
            event = eventService.findByCode(clazz);
            event.setCronExpression(cron);
            scheduleJobService.dynamicUpdate(event, tempId, SchsduleService.GROUP_SEND_SHORT_MESSAGE, params);
        } else {
            event = new Event();
            event.setWay(com.party.common.constant.Constant.EVENT_AUTO);
            event.setName(SchsduleService.JOB_SEND_SHORT_MESSAGE);
            event.setCode(clazz);
            event.setType("4");
            event.setCronExpression(cron);
            event.setIsSync(0);
            event.setClassName(clazz);
            event.setMethod(method);
            scheduleJobService.dynamicInsert(event, tempId, SchsduleService.GROUP_SEND_SHORT_MESSAGE, params);
        }

        ajaxResult.setSuccess(true);
        return ajaxResult;
    }

    /**
     * 删除短信
     * @param id: 模板id
     * @return
     */
    @Transactional
    public AjaxResult delQuartzForActivity(String id) {
        if (StringUtils.isEmpty(id)) {
            return AjaxResult.error("短信模板id不能为空");
        }
        TargetTemplate targetTemplate = targetTemplateService.get(id);
        if (null == targetTemplate) {
            return AjaxResult.error("找不到对应的模板 id= " + id);
        }
        // 移除定时器
        final String triggerName = SchsduleService.JOB_SEND_SHORT_MESSAGE.concat(SchsduleService.SEND_SHORT_MESSAGE_LINE).concat(id);
        final String group = SchsduleService.GROUP_SEND_SHORT_MESSAGE;
        scheduleJobService.removeTrigger(triggerName, group);
        // 删除短信
        targetTemplateService.delete(id);
        // 删除存的值在qrtz_data_map
        final String targetId = SchsduleService.PARAMS.concat(SchsduleService.SEND_SHORT_MESSAGE_LINE).concat(id);
        QuartzDataMap quartzDataMap = quartzDataMapService.findByTargetId(targetId);
        if (null != quartzDataMap) {
            quartzDataMapService.delete(quartzDataMap.getId());
        }
        return AjaxResult.success();
    }

    /**
     * 添加合作渠道
     *
     * @param activityId  活动id
     * @param mobile      手机号码
     * @param countryCode 区号
     */
    public void bindZcActivityRelation(String activityId, String mobile, String countryCode) {
        // 根据手机号和机构类型找用户
        // 如果存在，新增一个机构类型的用户，再添加一个合作渠道的角色
        // 如果不存在，添加一个合作渠道的角色
        MemberGroup member = memberGroupService.findByPhone(mobile, Constant.MEMBER_ORGANIZATION);
        String memberId;
        if (member == null) {
            memberId = memberGroupBizService.saveCosponsorMember(mobile, countryCode);
        } else {
            memberId = member.getId();
            memberGroupBizService.bindCosponsorRole(member);
        }
        if (StringUtils.isEmpty(memberId)) {
            throw new BusinessException("用户为空");
        }
        Activity activity = activityService.get(activityId);
        String oldCosponsorId = activity.getCosponsorId();
        activity.setCosponsorId(memberId);
        activityService.update(activity);

        if (StringUtils.isNotEmpty(oldCosponsorId)) {
            Integer count = activityService.findByCosponsorId(oldCosponsorId);
            if (null != count && count == 0) {
                memberGroupBizService.unBindCosponsorRole(oldCosponsorId);
            }
        }
    }

    public Map<String, Object> putZipInfo(String key) {
        String zipUrl = null;
        String uploadTime = null;
        String jedisValue = stringJedis.getValue(key);
        if (StringUtils.isNotEmpty(jedisValue)) {
            if (jedisValue.indexOf("sourceUrl") != -1) {
                Map<String, String> map = JSONObject.parseObject(jedisValue, Map.class);
                zipUrl = map.get("sourceUrl");
                uploadTime = map.get("uploadTime");
            } else {
                zipUrl = jedisValue;
            }
        }
        Map<String, Object> map = Maps.newHashMap();
        map.put("zipUrl", zipUrl);
        map.put("zipUploadTime", uploadTime);
        return map;
    }
}
